package main

import (
	"fmt"
	"os"
	"os/signal"
	"syscall"

	api "frigate/internal/http"
	"frigate/internal/raftnode"
	"frigate/internal/rpc"
	"frigate/utils"

	"github.com/spf13/cobra"
)

func main() {
	// 使用 cobra 创建根命令
	rootCmd := &cobra.Command{
		Use:   "frigate",
		Short: "A lightweight high-availability service based on Raft",
		Run: func(cmd *cobra.Command, args []string) {
			// 获取命令行参数
			nodeID, _ := cmd.Flags().GetString("id")
			addr, _ := cmd.Flags().GetString("addr")
			rpcAddr, _ := cmd.Flags().GetString("rpc-addr")
			dataDir, _ := cmd.Flags().GetString("data-dir")
			joinAddr, _ := cmd.Flags().GetString("join")
			bootstrap, _ := cmd.Flags().GetBool("bootstrap")
			apiAddr, _ := cmd.Flags().GetString("api-addr")
			debug, _ := cmd.Flags().GetBool("debug")

			// 设置日志
			utils.SetupLogger(debug)

			// 创建 Raft 节点配置
			nodeConfig := raftnode.Config{
				NodeID:    nodeID,
				Addr:      addr,
				RPCAddr:   rpcAddr,
				DataDir:   dataDir,
				JoinAddr:  joinAddr,
				Bootstrap: bootstrap,
			}

			// 创建并启动 Raft 节点
			node, err := raftnode.NewNode(nodeConfig)
			if err != nil {
				utils.Logger.Fatal().Err(err).Msg("Failed to create Raft node")
			}

			if err := node.Start(); err != nil {
				utils.Logger.Fatal().Err(err).Msg("Failed to start Raft node")
			}

			// 创建并启动 RPC 服务
			rpcServer := rpc.NewClusterServer(node)
			go func() {
				if err := rpcServer.Start(rpcAddr); err != nil {
					utils.Logger.Fatal().Err(err).Msg("Failed to start RPC server")
				}
			}()
			if debug {
				utils.Logger.Info().Str("addr", apiAddr).Msg("Start HTTP API server.")
				// 创建并启动 HTTP API 服务器
				apiServer := api.NewServer(node, apiAddr)
				if err := apiServer.Start(); err != nil {
					utils.Logger.Fatal().Err(err).Str("addr", apiAddr).Msg("Failed to start HTTP API server")
				}
			}

			// 等待中断信号以优雅地关闭服务
			sigCh := make(chan os.Signal, 1)
			signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
			<-sigCh

			utils.Logger.Info().Msg("Shutting down services...")

			// 关闭 Raft 节点
			if err := node.Shutdown(); err != nil {
				utils.Logger.Error().Err(err).Msg("Failed to shut down Raft node")
			}

			utils.Logger.Info().Msg("All services shut down successfully")
		},
	}

	// 添加命令行参数
	rootCmd.Flags().String("id", "1", "Node ID")
	rootCmd.Flags().String("addr", "127.0.0.1:8001", "Raft TCP listen address")
	rootCmd.Flags().String("rpc-addr", "127.0.0.1:9002", "gRPC listen address")
	rootCmd.Flags().String("data-dir", "./data", "Data directory for Raft storage")
	rootCmd.Flags().String("join", "", "Address of an existing node's RPC server to join")
	rootCmd.Flags().Bool("bootstrap", false, "Bootstrap the cluster as the first node")
	rootCmd.Flags().String("api-addr", "127.0.0.1:8081", "HTTP API listen address")
	rootCmd.Flags().Bool("debug", false, "Enable debug logging")

	// 执行根命令
	if err := rootCmd.Execute(); err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
}
